//
// Created by pc on 2022/5/21.
//

#ifndef HW11_12_STRING_H
#define HW11_12_STRING_H

#include <iostream>
using namespace std;

class String {
private:
    //真正用来存字符串的结构体
    struct Srep;
    Srep* rep;

public:
    class Cref;         // reference to char
    class Range {};

    String();
    String(const char*);
    String(const String&);

    ~String() = default;

    String& operator=(const char*);
    String& operator=(const String&);
    String& operator+=(const String&);
    friend ostream& operator<<(ostream&, const String&);

    void write(int i, char ch);
    /**
     * 不能在这里写，不然报错：member access into incomplete type
     * 因为先有String再有Srep，所以不能在这里直接调用Srep的成员和方法
     */
    char read(int i) const; /* { return rep->str[i] } */

    Cref operator[](int i);
    char operator[](int i) const;

};

struct String::Srep{
    char* str;          // 要存的字符串
    int size;           // 大小
    int ref_num;        // 字符串引用的个数

    /* 构造函数 */
    Srep(int n_size, const char* p);
    ~Srep() = default;

};

/**
 * 对于String中的每一个字符，我们使用这个类来管理对其的操作
 * 其实有点像管理类，GameCore这种，不直接调用被管理对象的函数，
 * 在管理类中间接调用被管理类的函数。
 * 只不过这里用的不是继承而是好朋友
 */
class String::Cref{
private:

    friend class String;

    //管理的字符串，其实一直就是String::this
    String& s;
    //我要访问的下标
    int i;
    //每当要操作String的时候，才会构造好Cref，因为下标到这个时候才是确定的
    Cref(String& ss, int ii) : s(ss), i(ii){}

public:

    //当读字符的时候调用
    operator char() const;

    //当写字符的时候调用
    void operator=(char c);

};



#endif //HW11_12_STRING_H
